#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <limits.h>
#include <sys/stat.h>
#include "common.h"
#include "monitor.h"

void follow_path(char *orig, char *newpath)
{
	/*char buf[PATH_MAX];
	char path[PATH_MAX];
	char temp[PATH_MAX];
	char temp1[PATH_MAX];

	char *tok;
	int i;
	int ret;
	memset(buf, 0, PATH_MAX);
	memset(path, 0, PATH_MAX);
	// convert the original path into absolute path

	strcpy(buf,orig);
	i = strlen(buf);
	tok = strtok(&buf[1], "/");
	path[0] = '/';
	i--;
	do
	{
		i--;
		//memset(path, 0, PATH_MAX);
		if (0 == tok) break;
		if (strcmp(tok, ".") == 0)
		{       i--;
			continue;
		}
		if (strcmp(tok, "..") == 0)
		{
			int loc = strlen(path) - 2;
			while (path[loc] != '/' && loc >= 0)
				loc--;
			path[loc + 1] = 0;
			i = i - 2;
			continue;
		}
		else
		{
			strcpy(temp1,path);
			strcat(path,tok);
			ret = readlink(path,temp,PATH_MAX);
			if(ret > 0)
			{
				temp[ret] = 0;
				if(temp[0] == '/')
					strcpy(path,temp);
				else
				{
					strcpy(path,temp1);
					strcat(path,temp);
				}
			}
			i = i - strlen(tok);
			if( i >= 0 )
				strcat(path,"/");
		}
	}while ((tok = strtok(NULL, "/")) != 0);
	strcpy(newpath,path);*/

	realpath(orig,newpath);
	if(newpath[strlen(newpath) -1] == '/' && (strcmp(newpath,"/") != 0))
		newpath[strlen(newpath) -1] = '\0';
}


void get_parent_dir(char *path, char *dest) //this will also follow the links to the parent if present
{
	char temp[PATH_MAX];
	int len;

	len = strlen(path) - 1;
	while(path[len] != '/' && len >= 0)
		len --;
	strncpy(temp,path,len);
	temp[len] = '\0';
	follow_path(temp,dest);	
}

int check_for_file_creation(char *path, char *appname)
{
	char temp[PATH_MAX];
	int ret;
	get_parent_dir(path,temp);
	ret = check_if_owned(temp,appname);
	return ret;
}

int check_for_sysdir(char *path)
{
	char temp[PATH_MAX];
	int ret;
	get_parent_dir(path,temp);
	ret = check_if_sysdir(temp);
	return ret;
}

int check_for_overwrite(char *path,char *appname)
{
	char temp[PATH_MAX];
	int ret;
	follow_path(path,temp);
	ret = check_if_owned(temp,appname);
	return ret;
}

int check_for_rename_unowned(char *path, char *appname)
{
	char temp[PATH_MAX];
	int ret,len,len1;
	get_parent_dir(path,temp);
	len = strlen(path) - 1;
        while(path[len] != '/' && len >= 0)
                len --;
	len1 = strlen(temp);
	while(path[len] != '\0')
		temp[len1++] = path[len++];
	temp[len1] = '\0';
	ret = check_if_owned(temp,appname);
	return ret;
}

int check_open_for_write()
{
  	printf("in check_open_for_write() API\n");
  	return 0;
}

int check_for_symlinks(char *path)
{
	struct stat st_buff;
	char temp[PATH_MAX],temp1[PATH_MAX];
	char *tok = NULL;
	char new[PATH_MAX];
	int ret = 0;
	strncpy(temp,path,PATH_MAX);
	strcpy(new,"");
	tok = strtok(temp + 1,"/");
	while(tok != NULL)
	{
		strcat(new,"/");
		strcat(new,tok);
		ret = readlink(new,temp1,PATH_MAX);
		if(ret > 0)
		{
			//means it is a link
			lstat(new,&st_buff);
			if(st_buff.st_uid != 0) //a non root symlink
				return -1;
		}
		tok = strtok(NULL,"/");
	} 
	return 0;
}

int check_for_file_type(char *fileName)
{
	char str[20];
	strcpy(str,fileName);
	char delim[] = ".";
	char *result = NULL;
	char *prevResult = NULL;
	result = strtok(str,delim);
	
	//get the extension from file name and store it at prevResult
	while(result != NULL)
	{
		prevResult = result;
		result = strtok(NULL,delim);
	}
	//printf("%s\n",prevResult);

	//Check for extension
	if(strcmp(prevResult,"html") == 0 || strcmp(prevResult,"php") == 0 || strcmp(prevResult,"js") == 0 || strcmp(prevResult,"asp") == 0 || strcmp(prevResult,"css") == 0 || strcmp(prevResult,"jsp") == 0)
		return 0;
	else
		return -1;
}

int check_for_allowed_syscalls(int syscall_no,int *allowed_list)
{
	int ret =-1,i=0;
	for(i=0;i<NO_OF_ALLOWED_SYSCALLS;i++){
		if(syscall_no == allowed_list[i]){
			ret=0;
			printf("RETURNING FROM ALLOWED SIGNAL %d %d\n",allowed_list[i],ret);
			break;
		}
	}

	return ret;
}

/*
   Ensure that all directories in a path are owned by same group
   Input: File Path, GID
   Output: 0 if allowed, -1 if not allowed
*/
int path_traversal(char path[], int gid)
{
	int length = strlen(path);
	char delimiters[] = "/";
	char *token = strtok(path, delimiters);

	char rebuilt_path[length];
	struct stat info;
	int a;
	strcpy(rebuilt_path, "/");

	while (token != NULL)
	{
		/* Check if folder is owned by GID */
		//printf("string: %s\n", token);
		strcat(rebuilt_path, token);
		//printf("rebuilt: %s\n", rebuilt_path);
		a = stat(rebuilt_path, &info);
		if (a < 0)
		{
			//printf("Fail\n");
			return -1;
		} else {
			//printf("GID: %d\n", info.st_gid);
			if (info.st_gid != gid)
			{
				//Fail
				return -1;
			}
		}
		token = strtok(NULL, delimiters);
		strcat(rebuilt_path, "/");
	}
	return 0;
}

/*
   Deny access to any CGI-Script which are owned by the user and allow for root
   Input: File Path
   Output: 0 if allowed, -1 if not allowed
*/
int check_for_cgi(char path[])
{
	struct stat info;
	int a = stat(path, &info);

	if(a < 0)
	{
		printf("Error, not found!\n");
		return 0;
	} else {
		/* Check if it has Execute permission */
		printf("Mode: %d\n",info.st_mode & S_IXUSR);
		if((info.st_mode & S_IXUSR) == 0)
		{
			//printf("FAIL: Not executable\n");
			return -1;
		} else {
			/* Check owner */
			if(info.st_uid == 0)
			{
				//printf("Pass!\n");
				return 0;
			} else {
				//printf("FAIL: Not owned by Root!\n");
				return -1;
			}
		}
	}
}

/* Check if the given path is a owned path 
	0 - if yes
	-1 - if no
*/
int check_if_owned(char *path, char *appname)
{
	char filename[100];
	char buf[256];
	FILE *list;
	char *test;
	int i;

	char *targetName = path;
	char aName[256];

	//Create Filename
	//strncpy(filename, appname, 95);
	strcpy(filename,"config/");	
	strcat(filename, appname);
	strcat(filename, ".list");

	//Open File
	list = fopen(filename,"r");

	i = fscanf(list, "%s", &buf);
	while(i != EOF)
	{
		//printf("%s", buf);
		//printf("strcmp: %d\n", strcmp(path, buf));

		if (strcmp(path, buf) == 0)
		{
			printf("%s and %s are equal!\n", path, buf);
			return 0;
		}
		i = fscanf(list, "%s", &buf);
	}

	//printf("FAIL\n");
	return -1;
}


/* Check if the given path is a owned path 
	-1 - if yes
	0 - if no
*/
int check_if_sysdir(char *path)
{
	char filename[100];
	char buf[256];
	FILE *list;
	char *test;
	int i;

	char *targetName = path;
	char aName[256];

	//Create Filename
	//strncpy(filename, appname, 95);
	strcpy(filename,"config/sysdir.list");	
	
	//Open File
	list = fopen(filename,"r");

	i = fscanf(list, "%s", &buf);
	while(i != EOF)
	{
		//printf("%s", buf);
		//printf("strcmp: %d\n", strcmp(path, buf));

		if (strcmp(path, buf) == 0)
		{
			printf("%s and %s are equal!\n", path, buf);
			return -1;
		}
		i = fscanf(list, "%s", &buf);
	}
	return 0;
}

int check_file_write_uid(char *path,pid_t pid)
{
	uid_t uid;
	struct stat st_buff;
	uid = get_euid(pid);
	stat(path,&st_buff);
	if(st_buff.st_uid == uid)
		return 0;
	return -1;
}

int check_file_write_gid(char *path,pid_t pid)
{
	gid_t gid;
	struct stat st_buff;
	gid = get_egid(pid);
	stat(path,&st_buff);
	if(st_buff.st_gid == gid)
		return 0;
	return -1;
}

int check_for_directory_traversal(char *path,pid_t pid)
{
	gid_t gid;
	int ret;
	//char temp[PATH_MAX];
	struct stat st_buff;
	gid = get_egid(pid);
	if(gid == 0)
		return 0;
	stat(path,&st_buff);
	if(st_buff.st_gid == gid)
                return 0;
        return -1;
	//follow_path(path,temp);
	//ret = path_traversal(temp, gid);	
}
